﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Clipboard2
{
    public partial class Form1 : Form
    {
        static string cut = "Friendess StreamCypCut.exe";
        static string cute = "Friendess StreamCypCutE.exe";
        static string one = "Friendess StreamCypOne.exe";
        static string pro = "Friendess StreamCypCutPro.exe";
        bool realExit = false;
        WinEventDelegate dele = null;
        byte[] lastBytes = new byte[] { };
        CypType lastCypType = CypType.None;
        List<CypApp> cypApps = new List<CypApp>();
        private System.Windows.Forms.ContextMenu contextMenu1;
        private System.Windows.Forms.MenuItem menuItem1;
        public Form1()
        {
            InitializeComponent();
            cypApps.Add(new CypApp(CypType.Cut, (title) => title.Contains("CypCut") && !title.Contains("CypCutE") && !title.Contains("CypCutPro"), cut));
            cypApps.Add(new CypApp(CypType.CutE, (title) => title.Contains("CypCutE"), cute));
            cypApps.Add(new CypApp(CypType.One, (title) => title.Contains("CypOne"), one));
            cypApps.Add(new CypApp(CypType.Pro, (title) => title.Contains("CypCutPro"), pro));
            dele = new WinEventDelegate(WinEventProc);
            IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT);

            this.contextMenu1 = new System.Windows.Forms.ContextMenu();
            this.menuItem1 = new System.Windows.Forms.MenuItem();

            // Initialize contextMenu1
            this.contextMenu1.MenuItems.AddRange(
                        new System.Windows.Forms.MenuItem[] { this.menuItem1 });

            // Initialize menuItem1
            this.menuItem1.Index = 0;
            this.menuItem1.Text = "E&xit";
            this.menuItem1.Click += new System.EventHandler(this.menuItem1_Click);
            this.notifyIcon1.ContextMenu = this.contextMenu1;

        }

        private void menuItem1_Click(object Sender, EventArgs e)
        {
            realExit = true;
            System.Diagnostics.Process.GetCurrentProcess().Kill();
            // Close the form, which closes the application.
            Application.Exit();
        }
        delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

        [DllImport("user32.dll")]
        static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

        private const uint WINEVENT_OUTOFCONTEXT = 0;
        private const uint EVENT_SYSTEM_FOREGROUND = 3;

        [DllImport("user32.dll")]
        static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

        private string GetActiveWindowTitle()
        {
            const int nChars = 256;
            IntPtr handle = IntPtr.Zero;
            StringBuilder Buff = new StringBuilder(nChars);
            handle = GetForegroundWindow();

            if (GetWindowText(handle, Buff, nChars) > 0)
            {
                return Buff.ToString();
            }
            return null;
        }

        public void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
        {
            string title = GetActiveWindowTitle();
            if (string.IsNullOrWhiteSpace(title))
            {
                return;
            }
            Log.Text += $"title={title}" + Environment.NewLine;
            string from = "";
            string to = "";
            var dataObject = Clipboard.GetDataObject();
            foreach (CypApp cypApp in this.cypApps)
            {
                if (cypApp.funcTitle(title))
                {
                    to = cypApp.cypType.ToString();
                    foreach (CypApp inCypApp in this.cypApps)
                    {
                        //inCypApp.cypType != cypApp.cypType &&
                        if (lastCypType == inCypApp.cypType && dataObject.GetDataPresent(inCypApp.exe))
                        {
                            from = inCypApp.cypType.ToString();
                            var st = (dataObject.GetData(inCypApp.exe) as MemoryStream).ToArray();
                            if (!st.SequenceEqual(lastBytes))
                            {
                                DataObject newObject = new DataObject();
                                newObject.SetData(cut, true, new MemoryStream(st.ToArray()));
                                newObject.SetData(cute, true, new MemoryStream(st.ToArray()));
                                newObject.SetData(one, true, new MemoryStream(st.ToArray()));
                                newObject.SetData(pro, true, new MemoryStream(st.ToArray()));
                                Clipboard.SetDataObject(newObject, true);
                                //Console.WriteLine($"已为{msg}设置剪贴板");
                                //Log.Text += $"已为{msg}设置剪贴板" + Environment.NewLine;
                                lastBytes = st;
                            }
                            break;
                        }
                    }
                    lastCypType = cypApp.cypType;
                    Log.Text += $"{from}->{to}" + Environment.NewLine;

                    break;
                }
            }


        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            realExit = true;
            notifyIcon1.Visible = false;
            Close();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!realExit)
            {
                e.Cancel = true;
                Opacity = 0;
                ShowInTaskbar = false;
                Hide();
            }
        }

        private void notifyIcon1_Click(object sender, EventArgs e)
        {
            Opacity = 100;
            ShowInTaskbar = true;
            Show();
            Focus();
        }

        private void chkTop_CheckedChanged(object sender, EventArgs e)
        {
            this.TopMost = chkTop.Checked;
        }
    }

    public enum CypType
    {
        Cut,
        CutE,
        One,
        Pro,
        None
    }
}
